package libs

import (
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/go-playground/validator/v10"
	"math/rand"
	"reflect"
	"runtime"
	"strings"
	"time"
)

// Random 随机字符串, numeric = true 为纯数字
func Random(lenNum int, numeric bool) string {
	var chars = []string{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
		"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
		"1", "2", "3", "4", "5", "6", "7", "8", "9", "0"}

	str := strings.Builder{}
	length := len(chars)
	if numeric {
		length = 10
	}

	rand.Seed(time.Now().UnixNano())
	for i := 0; i < lenNum; i++ {
		var l string
		if numeric {
			l = chars[52+rand.Intn(length)]
		} else {
			l = chars[rand.Intn(length)]
		}

		str.WriteString(l)
	}
	return str.String()
}

// GetSeparator  linux和windows中路径分隔符
func GetSeparator() (s string) {
	switch runtime.GOOS {
	case "linux":
		s = "/"
	default:
		s = "\\"
	}
	return s
}

// ErrorMsg 异常提示语
func ErrorMsg(err error, msg string) error {
	if msg == "" {
		msg = "异常"
	}
	return fmt.Errorf(msg+"：%w", err)
}

// If 三元操作符
func If(condition bool, param1, param2 interface{}) interface{} {
	if condition {
		return param1
	}
	return param2
}

// BindRequest 绑定参数校验参数
func BindRequest(ctx *gin.Context, data interface{}) (err error) {
	//绑定参数
	if ctx.Request.Method == "POST" {
		contentType := ctx.ContentType()
		if contentType == "application/json" {
			err = ctx.ShouldBindJSON(data)
		} else {
			err = ctx.ShouldBind(data)
		}
	} else {
		err = ctx.ShouldBind(data)
	}

	if err != nil {
		return errors.New("获取参数异常：" + err.Error())
	}

	//参数校验
	e := GoCheck(data)
	if e != "" {
		return errors.New(e)
	}
	return
}

// GoCheck 规则校验
func GoCheck(checkParams interface{}) (e string) {
	/**
	1.通过验证器校验参数
	2.获取验证器校验的结果
	3.比较校验结果,获取结构体中自定义的异常
	*/
	// 使用验证器验证做数据验证
	err := validator.New().Struct(checkParams)
	if err != nil {
		//获取验证校验到的异常数据
		if errors, ok := err.(validator.ValidationErrors); ok {
			for _, es := range errors {
				//过滤到的异常字段
				errField := es.Field()
				getObj := reflect.TypeOf(checkParams) //tag要使用reflect.Type去获取,获取异常字段在结构体中定义的异常文件
				if f, exist := getObj.Elem().FieldByName(errField); exist {
					return f.Tag.Get("msg")
				}
			}
		}
	}
	return ""
}

// IsSlice 校验是否是切片
func IsSlice(v interface{}) bool {
	return reflect.TypeOf(v).Kind() == reflect.Slice
}

// RandomInt 随机1-num范围的随机数
func RandomInt(num int) int {
	rand.Seed(time.Now().UnixNano())
	randomInt := rand.Intn(num) + 1
	return randomInt
}

// RandomFloat64 生成随机数
func RandomFloat64(num int) float64 {
	randomInt := RandomInt(num)
	return float64(randomInt)
}
